package main

import (
	"../deps/lessgo/logger"
	"../deps/lessgo/pagelet"
	"./conf"
	"./net"
	"./server"
	"./state"
	"./store"
	"flag"
	"fmt"
	"math/rand"
	"net/http"
	"net/rpc"
	"os"
	"os/signal"
	"runtime"
	"time"

	capi "./api/controllers"
	cmgr "./mgr/controllers"
)

var (
	flag_prefix = flag.String("prefix", "", "the prefix folder path")
	err         error
)

func init() {
	// Environment variable initialization
	runtime.GOMAXPROCS(runtime.NumCPU())
	rand.Seed(time.Now().UnixNano())
}

func main() {

	start := time.Now()

	//
	flag.Parse()
	if err := conf.Initialize(*flag_prefix); err != nil {
		fmt.Println("conf.Initialize error: %v", err)
		os.Exit(1)
	}

	//
	if err := state.Initialize(); err != nil {
		logger.Printf("fatal", "state.Initialize error: %v", err)
		os.Exit(1)
	}

	//
	if err := store.Initialize(); err != nil {
		logger.Printf("fatal", "store.Initialize error: %v", err)
		os.Exit(1)
	}

	//
	if err := server.LocalInitialize(); err != nil {
		logger.Printf("fatal", "server.LocalInitialize error: %v", err)
		os.Exit(1)
	}

	//
	if err := net.InitializeUDP(conf.Config.Port, server.ActionHandler); err != nil {
		logger.Printf("fatal", "net.Initialize error: %v", err)
		os.Exit(1)
	}

	//
	pp := new(server.Proposer)
	rpc.Register(pp)

	at := new(server.Acceptor)
	rpc.Register(at)

	lr := new(server.Learner)
	rpc.Register(lr)

	rpc.HandleHTTP()

	if cn, err := net.InitializeRpc(); err != nil {
		logger.Printf("fatal", "net.Initialize error: %v", err)
		os.Exit(1)
	} else {

		if err := cn.Listen(conf.Config.Port); err != nil {
			logger.Printf("fatal", "net.Initialize error: %v", err)
			os.Exit(1)
		}

		go http.Serve(cn.Ln, nil)
	}

	//
	server.LocalTrackerStart()
	server.LearnerTrackerStart()

	//
	pagelet.Config.UrlBasePath = "keeper"
	pagelet.Config.HttpPort = 1777
	pagelet.Config.I18n(conf.Config.Prefix + "/src/i18n/en.json")
	pagelet.Config.I18n(conf.Config.Prefix + "/src/i18n/zh_CN.json")

	pagelet.Config.RouteAppend("v1", "/:controller/:action")
	pagelet.RegisterController("v1", (*capi.Sys)(nil))
	pagelet.RegisterController("v1", (*capi.Self)(nil))
	pagelet.RegisterController("v1", (*capi.Data)(nil))
	pagelet.RegisterController("v1", (*capi.Bucket)(nil))
	pagelet.RegisterController("v1", (*capi.Stats)(nil))

	pagelet.Config.RouteStaticAppend("default", "/~", conf.Config.Prefix+"/static")
	pagelet.Config.RouteAppend("default", "/:controller/:action")

	pagelet.Config.ViewPath("default", conf.Config.Prefix+"/src/mgr/views")
	pagelet.RegisterController("default", (*cmgr.Index)(nil))
	pagelet.RegisterController("default", (*cmgr.Error)(nil))
	pagelet.RegisterController("default", (*cmgr.User)(nil))
	pagelet.RegisterController("default", (*cmgr.Bucket)(nil))
	pagelet.RegisterController("default", (*cmgr.Setup)(nil))

	pagelet.Run()

	//
	defer func() {
		if err := recover(); err != nil {

			store.Cmd("SAVE")
			time.Sleep(1e9)

			logger.Printf("fatal", "main panic: %v", err)
		}
	}()

	logger.Printf("info", "Started in %v", time.Since(start))

	//
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, os.Interrupt, os.Kill)
	s := <-quit

	store.Cmd("SAVE")

	logger.Printf("fatal", "Signal Quit: %v", s)
	time.Sleep(1e8)
}
